package edu.hawaii.myisern.action;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
import java.io.File;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import com.meterware.httpunit.SubmitButton;
import com.meterware.httpunit.UploadFileSpec;
import com.meterware.httpunit.WebConversation;
import com.meterware.httpunit.WebForm;
import com.meterware.httpunit.WebLink;
import com.meterware.httpunit.WebResponse;
import edu.hawaii.myisern.model.MyIsernModel;

/**
 * Demonstrates that the login, logout, and security filter are all working.
 * 
 * @author Ed Kim
 * @author Jon Lao
 * @author Jianfei Liao
 * @author Jared Sunouchi
 */
public class TestImportExport {
  /** Get the test host. */
  private String testHost = System.getProperty("test.host");
  /** A string representing the homepage title */
  private static final String HOMEPAGE_TITLE = "MyISERN 2.0 - Home";
  /** A string represent the username attribute */
  private static final String USERNAME_FIELD = "username";
  /** A string represent the password attribute */
  private static final String PASSWORD_FIELD = "password";
  /** A string represent the import page. */
  private static final Object IMPORT_TITLE = "MyISERN 2.0 - Import XML";
  /** A string to represent the submit form */
  private static final String SUBMIT_FORM = "SubmitForm";
  /** A string to represent the researchers file */
  private static final String RESEARCHERS_FILE = "researchersFile";
  /** A string to represent the researchers file */
  private static final String ORGANIZATIONS_FILE = "organizationsFile";
  /** A string to represent the researchers file */
  private static final String COLLABORATIONS_FILE = "collaborationsFile";
  /** The testing object. */
  private MyIsernModel myModel = MyIsernModel.getInstance();
  /** A string for "user.dir". */
  private static final String USER_DIR = "user.dir";
  /** The researchers XML file for testing. */
  private File researchersXmlFile = new File(System.getProperty(USER_DIR) + 
      "/xml/test/researchers.test.xml");
  /** The organizations XML file for testing. */
  private File organizationsXmlFile = new File(System.getProperty(USER_DIR) + 
      "/xml/test/organizations.test.xml");
  /** The collaborations XML file for testing. */
  private File collaborationsXmlFile = new File(System.getProperty(USER_DIR) + 
      "/xml/test/collaborations.test.xml");
  /** A text file that is invalid as XML data file. */
  private File invalidFile = new File(System.getProperty(USER_DIR) + 
  "/xml/test/testFile.in.txt");
  
  /**
   * Initialization before the tests start.
   */
  @Before
  public void initilize() {
    // export the current data for backup
    boolean isExported = this.myModel.exportXml(
        System.getProperty(USER_DIR) + "/researchers.tmp.xml", 
        System.getProperty(USER_DIR) + "/organizations.tmp.xml",
        System.getProperty(USER_DIR) + "/collaborations.tmp.xml");
    assertTrue("Checking data export", isExported);
  }
  
  /**
   * Tests the import and export XML functionalities.
   * 
   * @throws Exception If error occur.
   */
  @Test
  public void testImportExport() throws Exception {
    WebConversation conversation = new WebConversation();
    
    // retrieves the index.jsp page and check the title
    String url = this.testHost + "myisern";
    WebResponse response = conversation.getResponse(url);
    
    // login to the system
    WebForm loginForm = response.getFormWithID("LoginForm");
    loginForm.setParameter(USERNAME_FIELD, "username");
    loginForm.setParameter(PASSWORD_FIELD, "password");
    response = loginForm.submit();
    assertEquals("Logged in", HOMEPAGE_TITLE, response.getTitle());
    
    // click on the import link
    WebLink importLink = response.getLinkWithID("importXml");
    response = importLink.click();
    assertEquals("Checking page after clicking import link", IMPORT_TITLE, response.getTitle());
    
    // prepare the import files for researchers
    UploadFileSpec[] researchersUfs = {new UploadFileSpec(this.researchersXmlFile)};
    UploadFileSpec[] invalidResearchersUfs = {new UploadFileSpec(this.invalidFile)};
    
    // try to import researchers without data
    WebForm importForm = response.getFormWithID(SUBMIT_FORM);
    SubmitButton importButton = importForm.getSubmitButtonWithID("importResearchers");
    response = importForm.submit(importButton);
    assertEquals("Check empty researchers submit", IMPORT_TITLE, response.getTitle());
    // try to import researchers with invalid data
    importForm.setParameter(RESEARCHERS_FILE, invalidResearchersUfs);
    response = importForm.submit(importButton);
    assertEquals("Check invalid researchers submit", IMPORT_TITLE, response.getTitle());
    // try to import researchers with valid data
    importForm.setParameter(RESEARCHERS_FILE, researchersUfs);
    response = importForm.submit(importButton);
    assertEquals("Check valid researchers submit", IMPORT_TITLE, response.getTitle());
    
    
    // prepare the import files for organizations
    UploadFileSpec[] organizationsUfs = {new UploadFileSpec(this.organizationsXmlFile)};
    UploadFileSpec[] invalidOrganizationsUfs = {new UploadFileSpec(this.invalidFile)};
    
    // try to import organizations without data
    importForm = response.getFormWithID(SUBMIT_FORM);
    importButton = importForm.getSubmitButtonWithID("importOrganizations");
    response = importForm.submit(importButton);
    assertEquals("Check empty organizations submit", IMPORT_TITLE, response.getTitle());
    // try to import researchers with invalid data
    importForm.setParameter(ORGANIZATIONS_FILE, invalidOrganizationsUfs);
    response = importForm.submit(importButton);
    assertEquals("Check invalid organizations submit", IMPORT_TITLE, response.getTitle());
    // try to import researchers with valid data
    importForm.setParameter(ORGANIZATIONS_FILE, organizationsUfs);
    response = importForm.submit(importButton);
    assertEquals("Check valid organizations submit", IMPORT_TITLE, response.getTitle());

    // prepare the import files for collaborations
    UploadFileSpec[] collaborationsUfs = {new UploadFileSpec(this.collaborationsXmlFile)};
    UploadFileSpec[] invalidCollaborationsUfs = {new UploadFileSpec(this.invalidFile)};
    
    // try to import collaborations without data
    importForm = response.getFormWithID(SUBMIT_FORM);
    importButton = importForm.getSubmitButtonWithID("importCollaborations");
    response = importForm.submit(importButton);
    assertEquals("Check empty collaborations submit", IMPORT_TITLE, response.getTitle());
    // try to import collaborations with invalid data
    importForm.setParameter(COLLABORATIONS_FILE, invalidCollaborationsUfs);
    response = importForm.submit(importButton);
    assertEquals("Check invalid collaborations submit", IMPORT_TITLE, response.getTitle());
    // try to import collaborations with valid data
    importForm.setParameter(COLLABORATIONS_FILE, collaborationsUfs);
    response = importForm.submit(importButton);
    assertEquals("Check valid collaborations submit", IMPORT_TITLE, response.getTitle());
    
    
    // prepare import files for all types
    UploadFileSpec[] allUfsForRes = {new UploadFileSpec(this.researchersXmlFile)};
    UploadFileSpec[] allUfsForInvalidRes = {new UploadFileSpec(this.invalidFile)};
    UploadFileSpec[] allUfsForOrg = {new UploadFileSpec(this.organizationsXmlFile)};
    UploadFileSpec[] allUfsForInvalidOrg = {new UploadFileSpec(this.invalidFile)};
    UploadFileSpec[] allUfsForCollab = {new UploadFileSpec(this.collaborationsXmlFile)};
    UploadFileSpec[] allUfsForInvalidCollab = {new UploadFileSpec(this.invalidFile)};
    
    // try to import all without any data
    importForm = response.getFormWithID(SUBMIT_FORM);
    importButton = importForm.getSubmitButtonWithID("importAll");
    response = importForm.submit(importButton);
    assertEquals("Check empty submit", IMPORT_TITLE, response.getTitle());
    // try to import all with invalid data
    importForm.setParameter(RESEARCHERS_FILE, allUfsForInvalidRes);
    importForm.setParameter(ORGANIZATIONS_FILE, allUfsForInvalidOrg);
    importForm.setParameter(COLLABORATIONS_FILE, allUfsForInvalidCollab);
    response = importForm.submit(importButton);
    assertEquals("Check invalid submit", IMPORT_TITLE, response.getTitle());
    // try to import all with valid data
    importForm.setParameter(RESEARCHERS_FILE, allUfsForRes);
    importForm.setParameter(ORGANIZATIONS_FILE, allUfsForOrg);
    importForm.setParameter(COLLABORATIONS_FILE, allUfsForCollab);
    response = importForm.submit(importButton);
    assertEquals("Check valid submit", IMPORT_TITLE, response.getTitle());
    
    
    
    
    // click on the export link
    WebLink exportLink = response.getLinkWithID("exportXml");
    exportLink.click();
    // ensure the javascript alert dialog pops up
    // this is somehow null
//    assertEquals("Checking for export pop-up", "something", conversation.getNextAlert());
  }
  
  /**
   * Recover the data after testing.
   */
  @After
  public void recover() {
    // import from the tmp files to restore the data
    boolean isImported = myModel.
        importResearchersXml(System.getProperty(USER_DIR) + "/researchers.tmp.xml");
    assertTrue("Checking researchers XML file import", isImported);
    isImported = myModel.
        importOrganizationsXml(System.getProperty(USER_DIR) + "/organizations.tmp.xml");
    assertTrue("Checking organizations XML file import", isImported);
    isImported = myModel.
        importCollaborationsXml(System.getProperty(USER_DIR) + "/collaborations.tmp.xml");
    assertTrue("Checking collaborations XML file import", isImported);
    
    // delete the tmp files
    File file = new File(System.getProperty(USER_DIR) + "/researchers.tmp.xml");
    boolean isDeleted = file.delete();
    assertTrue("Checking researchers tmp file deletion", isDeleted);
    file = new File(System.getProperty(USER_DIR) + "/organizations.tmp.xml");
    file.delete();
    assertTrue("Checking organizations tmp file deletion", isDeleted);
    file = new File(System.getProperty(USER_DIR) + "/collaborations.tmp.xml");
    file.delete();
    assertTrue("Checking collaborations tmp file deletion", isDeleted);
    
    // shuts down the database
    //assertTrue("shutting down", this.myModel.shutDown());
  }
}